//
// This file is part of cpp-lib, a library of C++ functions and classes.
// Cpp-lib is copyright (C) 2004 and onwards, The CPL Interest Group.
// 
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
// 
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
// General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this library (see the file COPYING); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
// 02111-1307  USA
//
// $Id$
//

#include <iostream>
#include <exception>
#include <stdexcept>
#include <memory>
#include <vector>

#include "cpp-lib/blowfish.h"
#include "cpp-lib/crypt_stream.h"
#include "cpp-lib/util.h"
#include "cpp-lib/sys/file.h"

#include "test_key.h"


using namespace cpl::crypt       ;
using namespace cpl::util        ;
using namespace cpl::util::file  ;


namespace {

std::string const suffix = ".crypt" ;


void usage( std::string const& prog ) {

  std::cerr 
	<< "Usage: " << prog << "<name>[.bf]\n" 
	<< "Read ciphertext from <name>.bf, write plaintext to <name>, OR\n"
	<< "read plaintext from <name>, write ciphertext to <name>.bf.\n" 
	;

}


} // anonymous namespace



int main( int argc , char const * const * const argv ) {


  if( argc != 2 ) { usage( argv[ 0 ] ) ; return 1 ; }

  std::string const name = argv[ 1 ] ;

  try {

  std::vector< char > const K = key() ;
  std::vector< char > const I = IV () ;

  blowfish bf( K ) ;

  if( name.find( suffix ) == name.size() - suffix.size() ) {

	// Name ends in .bf -> decrypt.
	
	std::string const bname = basename( name , suffix ) ;
	
	std::auto_ptr< std::istream > is = open_read ( bf , I , name  ) ;
	std::auto_ptr< std::ostream > os = open_write(          bname ) ;

	char c ;
	while( EOF != ( c = is->get() ) ) { *os << c ; }

  } else {

	// Name does not end in .bf -> encrypt.
	
	std::string const cname = name + suffix ;

	std::auto_ptr< std::istream > is = open_read (          name  ) ;
	std::auto_ptr< std::ostream > os = open_write( bf , I , cname ) ;

	char c ;
	while( EOF != ( c = is->get() ) ) { *os << c ; }

  }

  } catch( std::exception const& e ) { die( e.what() ) ; }

}
